package org.spider.resolver;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class ModelLoaderRegisteCenter {

    private Map<String,ModelLoader> loaderCache = new ConcurrentHashMap<>(12);

    public void registeLoader(ModelLoader...modelLoader){
        Assert.noNullElements(modelLoader);
        doBindModelLoader(modelLoader);
    }

    public List<ModelLoader> getLoaders(){
        return CollectionUtil.newArrayList(loaderCache.values());
    }

    private void doBindModelLoader(ModelLoader...modelLoaders){
        for(ModelLoader modelLoader : modelLoaders){
            Type[] genericInterfaces = modelLoader.getClass().getGenericInterfaces();
            for(Type type : genericInterfaces){
                ParameterizedType parameterizedType = (ParameterizedType) type;
                String typeName = parameterizedType.getRawType().getTypeName();
                if(ModelLoader.class.getName().equals(typeName)){
                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                    if(actualTypeArguments != null && actualTypeArguments.length > 0){
                        String genTypeName = actualTypeArguments[0].getTypeName();
                        loaderCache.putIfAbsent(genTypeName,modelLoader);
                    }
                }
            }
        }
    }

    private ModelLoader getDesignationLoader(Class clazz){
        return loaderCache.get(clazz.getCanonicalName());
    }

    public ModelLoader getDesignationLoader(Class...clazz){
        for(Class cla : clazz){
            ModelLoader modelLoader = this.getDesignationLoader(cla);
            if(modelLoader != null) return modelLoader;
        }
        return null;
    }
}
